package com.clear.creational;

import java.io.Serializable;
import java.util.Objects;

/**
 * 懒汉单例 双重检查锁 线程安全，满足懒加载
 * todo 开发推荐使用
 */
public class DclSingleton implements Serializable {
    // todo 创建对象，不是原子性操作，即使使用了双重检查锁，也可能在创建过程中产生半初始状态
    // volatile如果不加可能会出现半初始化的对象
    // 现在用的高版本的 Java 已经在 JDK 内部实现中解决了这个问题（解决的方法很简单，只要把对象 new 操作和初始化操作设计为原子操作，就自然能禁止重排序）,为了兼容性我们加上
    private volatile static DclSingleton INSTANCE;

    private DclSingleton() {
        // todo 不让其使用反射创建对象
        if (INSTANCE != null){
            throw new RuntimeException("该实例只允许实例化一次!!!");
        }
    }

    public static DclSingleton getInstance() {
        if (null == INSTANCE) {
            synchronized (DclSingleton.class) {
                if (null == INSTANCE) {
                    INSTANCE = new DclSingleton();
                }
            }
        }
        return INSTANCE;
    }

    // todo 加上这个方法
    public Object readResolve(){
        return INSTANCE;
    }
}
